package com.xbongbong.paas.service.impl;

import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.pojo.CallReckonPojo;
import com.xbongbong.paas.pojo.dto.CallAccountUserIdInDTO;
import com.xbongbong.paas.pojo.dto.CallCenterAccountUserInfoDTO;
import com.xbongbong.paas.pojo.dto.CallCenterAdminDTO;
import com.xbongbong.paas.pojo.dto.CallCenterAgentDTO;
import com.xbongbong.paas.pojo.dto.CallCenterSupervisorDTO;
import com.xbongbong.paas.pojo.dto.CallSocketReckonDTO;
import com.xbongbong.paas.pojo.dto.CallUpdateAccountDTO;
import com.xbongbong.paas.pojo.vo.CallCenterAccountGetByMobileVO;
import com.xbongbong.paas.pojo.vo.CallCenterAccountUserInfoVO;
import com.xbongbong.paas.pojo.vo.CallCenterAdminVO;
import com.xbongbong.paas.pojo.vo.CallCenterAgentVO;
import com.xbongbong.paas.pojo.vo.CallCenterOrgGetByCorpIdVO;
import com.xbongbong.paas.pojo.vo.CallCenterSupervisorVO;
import com.xbongbong.paas.pojo.vo.CallSocketReckonVO;
import com.xbongbong.paas.pojo.vo.CallUpdateAccountVO;
import com.xbongbong.paas.pojo.vo.DuYanAccountVO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisConstant;
import com.xbongbong.paas.service.CallCenterAccountService;
import com.xbongbong.paas.service.CallCenterAgentStrategyService;
import com.xbongbong.paas.service.CallCenterCommonService;
import com.xbongbong.paas.service.CallCenterOrganizationService;
import com.xbongbong.paas.service.CallCenterTeamService;
import com.xbongbong.paas.service.DuYanHttpService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.XbbResponse;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.enums.CallCenterTypeEnum;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.CallCenterErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.DuYanErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.statistic.result.pojo.TotalAndAggPojo;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.constant.callcenter.CallCenterConstant;
import com.xbongbong.saas.domain.entity.CallCenterAccountEntity;
import com.xbongbong.saas.domain.entity.CallCenterTeamEntity;
import com.xbongbong.saas.help.CallReckonHelp;
import com.xbongbong.saas.model.CallCenterAccountModel;
import com.xbongbong.sys.domain.dao.UserDepartmentDao;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.UserModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author youli.chen
 * @version v1.0
 * @description: 呼叫中心账户 业务层实现类
 * @date 2019/2/12 15:51
 * @since v1.0
 */
@Service("callCenterAccountService")
public class CallCenterAccountServiceImpl implements CallCenterAccountService {

    private static final Logger LOG = LoggerFactory.getLogger(CallCenterAccountServiceImpl.class);

    @Resource
    private UserModel userModel;
    @Resource
    private CallCenterAccountModel callCenterAccountModel;
    @Resource
    private DuYanHttpService duYanHttpService;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private CallCenterCommonService callCenterCommonService;
    @Resource
    private CallCenterOrganizationService callCenterOrganizationService;
    @Resource
    private CallCenterTeamService callCenterTeamService;
    @Resource
    private CallCenterAgentStrategyService callCenterAgentStrategyService;
    @Resource
    private CallReckonHelp callReckonHelp;
    @Resource
    private UserDepartmentDao userDepartmentDao;

    /**
     * 根据销帮帮CRM的用户信息获取话务中心的平台账号
     *
     * @param callCenterAccountUserInfoDTO
     * @return CallCenterAccountUserInfoVO 话务中心平台账户 不存在则返回null
     */
    @Override
    public CallCenterAccountUserInfoVO getByXbbUserInfo(CallCenterAccountUserInfoDTO callCenterAccountUserInfoDTO) throws XbbException {
        Map<String, Object> params = new HashMap<>(6);
        params.put("corpid", callCenterAccountUserInfoDTO.getCorpid());
        params.put("userId", callCenterAccountUserInfoDTO.getUserId());
        params.put("moduleType", callCenterAccountUserInfoDTO.getModuleType());
        params.put("del", DelEnum.NORMAL.getDel());
        params.put("start", 0);
        params.put("pageNum", 1);
        List<CallCenterAccountEntity> callCenterAccountList = callCenterAccountModel.findEntitys(params);
        CallCenterAccountUserInfoVO userInfoVO = new CallCenterAccountUserInfoVO();
        if (callCenterAccountList.size() != 0) {
            BeanUtils.copyProperties(callCenterAccountList.get(0), userInfoVO);
        } else {
            userInfoVO = null;
        }
        return userInfoVO;
    }

    /**
     * 根据号码获取账号详情
     *
     * @param mobile     号码
     * @param moduleType 话务中心识别号
     * @return CallCenterAccountGetByMobileVO 根据号码获取账号详情回参
     * @throws XbbException
     */
    @Override
    public CallCenterAccountGetByMobileVO getByMobile(String mobile, Integer moduleType) throws XbbException {
        Map<String, Object> params = new HashMap<>(5);
        params.put("mobile", mobile);
        params.put("moduleType", moduleType);
        // 只有del=1的客户的手机号不能重复
        params.put("negDel", 1);
        params.put("start", 0);
        params.put("pageNum", 1);
        List<CallCenterAccountEntity> callCenterAccountList = callCenterAccountModel.findEntitys(params);
        CallCenterAccountGetByMobileVO getByMobileVO = new CallCenterAccountGetByMobileVO();
        if (callCenterAccountList.size() != 0) {
            BeanUtils.copyProperties(callCenterAccountList.get(0), getByMobileVO);
        }
        return getByMobileVO;
    }

    /**
     * 更新第三方话务中心的账号信息
     *
     * @param apiKey                  平台维护的apiKey
     * @param callCenterAccountEntity 本地维护的话务中心账号信息
     * @return boolean 是否更新成功
     * @throws XbbException 封装的异常
     * @author youli.cehn
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateThirdPlatformAccount(String apiKey, CallCenterAccountEntity callCenterAccountEntity) throws XbbException {
        if (Objects.equals(callCenterAccountEntity.getModuleType(), CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode())) {
            DuYanAccountVO accountVO =
                    new DuYanAccountVO(Long.parseLong(callCenterAccountEntity.getAccountId()),
                            callCenterAccountEntity.getName(),
                            callCenterAccountEntity.getTitle(),
                            callCenterAccountEntity.getMobile()
                    );
            DuYanAccountVO duYanAccountPojo = duYanHttpService.updateAccount(apiKey, accountVO);
            boolean check = duYanAccountPojo != null;
            if (check) {
                callCenterAccountModel.update(callCenterAccountEntity);
            }
            return check;
        }
        return false;
    }

    /**
     * 在话务中心注册员工并同步本地账号系统
     *
     * @param registerUserEntity 用户表查询出来的用户
     * @param moduleType         平台信息，参考CallCenterTypeEnum
     * @param apiKey             平台维护的apiKey
     * @return boolean 是否更新成功
     * @throws XbbException 封装的异常
     * @author youli.cehn
     */
    @Override
    public boolean saveAccount(UserEntity registerUserEntity, Integer moduleType, String apiKey) throws XbbException {
        if (registerUserEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
        }
        String corpid = registerUserEntity.getCorpid();
        String userId = registerUserEntity.getUserId();
        String name = registerUserEntity.getName();
        String title = registerUserEntity.getPosition();
        String mobile = registerUserEntity.getMobile();

        CallCenterAccountUserInfoDTO userInfoDTO = new CallCenterAccountUserInfoDTO();
        userInfoDTO.setCorpid(corpid);
        userInfoDTO.setUserId(userId);
        userInfoDTO.setModuleType(moduleType);
        CallCenterAccountUserInfoVO userInfoVO = getByXbbUserInfo(userInfoDTO);

        CallCenterAccountEntity callCenterAccountEntity = new CallCenterAccountEntity();
        if (userInfoVO == null) {
            callCenterAccountEntity = null;
        } else {
            BeanUtils.copyProperties(userInfoVO, callCenterAccountEntity);
        }
        DuYanAccountVO register = new DuYanAccountVO();
        register.setName(name);
        register.setTitle(title);
        register.setMobile(mobile);

        if (Objects.equals(moduleType, CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode())) {
            DuYanAccountVO duYanAccountVO;
            if (callCenterAccountEntity == null) {
                callCenterAccountEntity = new CallCenterAccountEntity(corpid, userId, null,
                        moduleType, name, title, mobile);
                // 度言平台注册
                duYanAccountVO = duYanHttpService.registerAccount(apiKey, register);
            } else {
                register.setAccountId(Long.parseLong(callCenterAccountEntity.getAccountId()));
                duYanAccountVO = duYanHttpService.updateAccount(apiKey, register);
            }
            if (duYanAccountVO == null || duYanAccountVO.getAccountId() == null) {
                throw new XbbException(DuYanErrorCodeEnum.API_ERROR_302003);
            }
            callCenterAccountEntity.setAccountId(duYanAccountVO.getAccountId().toString());
            callCenterAccountEntity.setName(name);
            if (StringUtil.isNotEmpty(title)) {
                callCenterAccountEntity.setTitle(title);
            }
            if (StringUtil.isNotEmpty(mobile)) {
                callCenterAccountEntity.setMobile(mobile);
            }
            return callCenterAccountModel.insert(callCenterAccountEntity) > 0;
        } else if (Objects.equals(moduleType, CallCenterTypeEnum.CALL_CENTER_XBB.getCode())) {
            if (callCenterAccountEntity == null) {
                callCenterAccountEntity = new CallCenterAccountEntity(corpid, userId, null, moduleType, name, title, mobile);
            }
            callCenterAccountEntity.setName(name);
            if (StringUtil.isNotEmpty(title)) {
                callCenterAccountEntity.setTitle(title);
            }
            if (StringUtil.isNotEmpty(mobile)) {
                callCenterAccountEntity.setMobile(mobile);
            }
            return callCenterAccountModel.insert(callCenterAccountEntity) > 0;
        }
        return false;
    }

    /**
     * 查询指定用户Id列表的用户
     *
     * @param corpid     公司id
     * @param moduleType 平台信息，参考AppStoreTypeEnum
     * @return Integer 坐席数量
     * @throws XbbException 封装的异常
     * @author youli.cehn
     */
    @Override
    public Integer countAgentNum(String corpid, Integer moduleType) throws XbbException {
        Map<String, Object> params = new HashMap<>(16);
        params.put("corpid", corpid);
        params.put("moduleType", moduleType);
        params.put("isAgent", 1);
        params.put("negDel", DelEnum.DELETE.getDel());
        Integer agentNum = callCenterAccountModel.getEntitysCount(params);
        if (moduleType.equals(CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode())) {
            String agentNumStr = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_AGENT_NUM,
                    corpid + StringConstant.COLON + moduleType);

            if (StringUtil.isNotEmpty(agentNumStr) && StringUtil.isNumeric(agentNumStr)) {
                agentNum = Integer.parseInt(agentNumStr);
            } else {
                paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_AGENT_NUM, corpid + StringConstant.COLON + moduleType,
                        agentNum.toString(), RedisConstant.COMMON_DURATION);
            }
        } else if (moduleType.equals(CallCenterTypeEnum.CALL_CENTER_XBB.getCode())) {
            paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_AGENT_NUM, corpid + StringConstant.COLON + moduleType,
                    agentNum.toString(), RedisConstant.COMMON_DURATION);
        }

        return agentNum < 0 ? 0 : agentNum;
    }

    /**
     * 员工设置坐席状态
     *
     * @param callCenterAgentDTO 员工设置坐席状态入参
     * @return CallCenterAccountGetByMobileVO 员工设置坐席状态回参
     * @throws XbbException 封装的异常
     * @author youli.cehn
     */
    @Override
    public XbbResponse<CallCenterAgentVO> agent(CallCenterAgentDTO callCenterAgentDTO) throws XbbException {
        CallCenterAgentVO callCenterAgentVO;
        String corpid = callCenterAgentDTO.getCorpid();
        Integer moduleType = callCenterAgentDTO.getModuleType();
        Boolean isAgent = callCenterAgentDTO.getIsAgent();
        Long depId = callCenterAgentDTO.getDepId();
        String agentUserId = callCenterAgentDTO.getAgentUserId();

        if (callCenterCommonService.notCallCenterModule(moduleType)) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301029);
        }

        CallCenterOrgGetByCorpIdVO getByCorpIdVO = callCenterOrganizationService.getByCorpId(corpid, moduleType);
        if (getByCorpIdVO == null) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301001);
        }
        String apiKey = getByCorpIdVO.getApikey();
        // 判断企业是否已经设置了超过最大坐席上限(已经开通的坐席数量)
        Integer agentNum = countAgentNum(corpid, moduleType);
        // 当月已经付费坐席数
        Integer paidAgentNum = getByCorpIdVO.getPaidAgentNum();

        callCenterCommonService.syncCallCenterDepartment(corpid, moduleType, depId, null);

        LOG.info("设置坐席时apikey:"+apiKey);
        CallCenterAccountUserInfoVO userInfoVO = callCenterCommonService.registerAccount(apiKey, moduleType, corpid, agentUserId);
        if (userInfoVO == null) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301030);
        }

        CallCenterTeamEntity teamEntity = callCenterTeamService.getByXbbDepInfo(corpid, depId, moduleType);
        if (teamEntity == null) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301031);
        }

        if (isAgent) {
            isAgent(corpid, moduleType, depId, paidAgentNum, teamEntity, userInfoVO, getByCorpIdVO, agentUserId, agentNum);
        } else {
            // 取消坐席
            if (userInfoVO.getIsAgent() == 0) {
                // 当前用户压根还不是坐席
                throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301032);
            }
            // 团队主管必须是坐席
            if (userInfoVO.getIsSupervisor() == 1) {
                throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301013);
            }
        }
        callCenterAgentVO = originTeamAgent(userInfoVO, apiKey, teamEntity, isAgent, moduleType, agentNum, corpid);
        return new XbbResponse<>(callCenterAgentVO);
    }

    /**
     * 员工设置团队主管
     *
     * @param callCenterSupervisorDTO 员工设置团队主管入参
     * @return CallCenterSupervisorVO 员工设置团队主管回参
     * @throws XbbException 封装的异常
     * @author youli.cehn
     */
    @Override
    public XbbResponse<CallCenterSupervisorVO> accountSupervisor(CallCenterSupervisorDTO callCenterSupervisorDTO) throws XbbException {
        CallCenterSupervisorVO callCenterSupervisorVO = new CallCenterSupervisorVO();
        String corpid = callCenterSupervisorDTO.getCorpid();
        Integer moduleType = callCenterSupervisorDTO.getModuleType();
        Boolean isSupervisor = callCenterSupervisorDTO.getIsSupervisor();
        String supervisorUserId = callCenterSupervisorDTO.getSupervisorUserId();

        Long depId = callCenterSupervisorDTO.getDepId();
        if(Objects.equals(depId, 1L)){
            Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("del", DelEnum.NORMAL.getDel());
            param.put("userId", supervisorUserId);
            List<Long> getDepIds = userDepartmentDao.getDepIds(param);
            if(!getDepIds.isEmpty()){
                depId = getDepIds.get(0);
            }
        }

        if (callCenterCommonService.notCallCenterModule(moduleType)) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301029);
        }

        String apiKey = null;
        if (moduleType.equals(CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode())) {
            apiKey = callCenterOrganizationService.getApiKey(corpid, moduleType);
            if (StringUtil.isEmpty(apiKey)) {
                throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301001);
            }
        }
        callCenterCommonService.syncCallCenterDepartment(corpid, moduleType, depId, null);

        CallCenterAccountUserInfoVO userInfoVO = callCenterCommonService.registerAccount(apiKey, moduleType, corpid, supervisorUserId);
        if (userInfoVO == null) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301030);
        }
        if (isSupervisor) {
            // 设为团队主管需要先校验部门是否有更改
            if (!Objects.equals(userInfoVO.getDepId(), null) && !Objects.equals(depId, userInfoVO.getDepId())) {
                // 本次需要设置的员工的部门与员工本身的部门不符，提示用户切换部门
                String hint = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_SUPERVISOR_CHANGE_DEP,
                        corpid + StringConstant.COLON + moduleType + StringConstant.COLON + supervisorUserId);
                if (StringUtil.isNotEmpty(hint)) {
                    // 已经提示过用户，进行切换部门保留角色的操作
                    if (!callCenterCommonService.changeAccountDep(corpid, userInfoVO, depId)) {
                        throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301033);
                    }
                } else {
                    paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_SUPERVISOR_CHANGE_DEP,
                            corpid + StringConstant.COLON + moduleType + StringConstant.COLON + supervisorUserId,
                            "changeDepHint", 60);
                    CallCenterTeamEntity originalTeamEntity = callCenterTeamService.getByXbbDepInfo(corpid, userInfoVO.getDepId(), moduleType);
                    if (originalTeamEntity == null) {
                        throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301034);
                    }
                    CallCenterTeamEntity newTeamEntity = callCenterTeamService.getByXbbDepInfo(corpid, depId, moduleType);
                    if (newTeamEntity == null) {
                        throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301031);
                    }
                    if(originalTeamEntity.getName() == null || newTeamEntity.getName() == null){
                        throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301087);
                    }
                    String errMsg = String.format(I18nMessageUtil.getMessage(CallCenterConstant.ERROR_MESSAGE_MEMBER_ONLY_BELONG_ONE_DEPARTMENT), userInfoVO.getName(),
                            originalTeamEntity.getName(), newTeamEntity.getName());
                    throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301012, errMsg);
                }
            }
        }
        CallCenterAccountEntity accEntity = new CallCenterAccountEntity();
        BeanUtils.copyProperties(userInfoVO, accEntity);
        if (!setSupervisor(apiKey, accEntity, isSupervisor)) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301035);
        }
        return new XbbResponse<>(callCenterSupervisorVO);
    }

    /**
     * 员工设置超管状态
     *
     * @param callCenterAdminDTO 员工设置超管状态入参
     * @return CallCenterAdminVO 员员工设置超管状态回参
     * @throws XbbException 封装的异常
     * @author youli.cehn
     */
    @Override
    public XbbResponse<CallCenterAdminVO> accountAdmin(CallCenterAdminDTO callCenterAdminDTO) throws XbbException {
        CallCenterAdminVO callCenterAdminVO = new CallCenterAdminVO();
        String corpid = callCenterAdminDTO.getCorpid();
        Integer moduleType = callCenterAdminDTO.getModuleType();
        Boolean isAdmin = callCenterAdminDTO.getIsAdmin();
        String adminUserId = callCenterAdminDTO.getAdminUserId();

        if (callCenterCommonService.notCallCenterModule(moduleType)) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301029);
        }

        String apiKey = null;
        if (moduleType.equals(CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode())) {
            apiKey = callCenterOrganizationService.getApiKey(corpid, moduleType);
            if (StringUtil.isEmpty(apiKey)) {
                throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301001);
            }
        }

        CallCenterAccountUserInfoVO userInfoVO = callCenterCommonService.registerAccount(apiKey, moduleType, corpid, adminUserId);
        if (userInfoVO == null) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301030);
        }
        CallCenterAccountEntity accEntity = new CallCenterAccountEntity();
        BeanUtils.copyProperties(userInfoVO, accEntity);
        if (!setAdmin(apiKey, accEntity, isAdmin)) {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301036);
        }
        return new XbbResponse<>(callCenterAdminVO);
    }

    /**
     * 获取并更新客户端及版本号
     *
     * @param callUpdateAccountDTO 获取并更新客户端及版本号入参
     * @return CallUpdateAccountVO 获取并更新客户端及版本号回参
     * @throws XbbException 封装的异常
     * @author youli.cehn
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public XbbResponse<CallUpdateAccountVO> updateAccount(CallUpdateAccountDTO callUpdateAccountDTO) throws XbbException {
        CallUpdateAccountVO callUpdateAccountVO = new CallUpdateAccountVO();
        String nowFirmwareVer = callUpdateAccountDTO.getModel() + "_" + callUpdateAccountDTO.getFirmWareVersion();
        //版本获取更新只限于销帮帮呼叫中心
        Integer moduleType = callUpdateAccountDTO.getModuleType();
        if (Objects.equals(moduleType, CallCenterTypeEnum.CALL_CENTER_XBB.getCode())) {
            CallCenterAccountEntity callCenterAccountEntity = new CallCenterAccountEntity();
            callCenterAccountEntity.setCorpid(callUpdateAccountDTO.getCorpid());
            callCenterAccountEntity.setUserId(callUpdateAccountDTO.getUserId());
            callCenterAccountEntity.setModuleType(moduleType);
            callCenterAccountEntity.setNowClientVer(callUpdateAccountDTO.getClientVersion());
            callCenterAccountEntity.setNowFirmwareVer(nowFirmwareVer);
            callCenterAccountModel.updateVersion(callCenterAccountEntity);
        }
        return new XbbResponse<>(callUpdateAccountVO);
    }

    /**
     * 呼叫统计
     *
     * @param callSocketReckonDTO 入参
     * @return com.xbongbong.paas.pojo.vo.CallSocketReckonVO
     * @author 徐俊杰
     * @date 2019/6/26 15:30
     * @since v1.0
     */
    @Override
    public CallSocketReckonVO reckon(CallSocketReckonDTO callSocketReckonDTO) throws XbbException {
        //入参(corpid,userId)
        CallReckonPojo callReckonPojo = new CallReckonPojo();
        BeanUtil.copyProperties(callSocketReckonDTO, callReckonPojo, true);
        //统计
        TotalAndAggPojo totalAndAggPojo = callReckonHelp.callDuration(callReckonPojo);
        CallSocketReckonVO callSocketReckonVO = new CallSocketReckonVO();
        //今日呼出数
        int count = totalAndAggPojo.getTotal();
        callSocketReckonVO.setCount(count);
        //今日呼出时长
        int agg = totalAndAggPojo.getAgg();
        String secondToTime = DateUtil.secondToTimeTip(agg);
        callSocketReckonVO.setDuration(secondToTime);
        //呼出成功数
        int successCount = callReckonHelp.callSuccessCount(callReckonPojo);
        callSocketReckonVO.setSuccessCount(successCount);
        return callSocketReckonVO;
    }

    /**
     * 设置为话务中心的坐席
     *
     * @param apiKey                  平台维护的apiKey
     * @param callCenterAccountEntity 话务平台员工信息
     * @param callCenterTeamEntity    话务平台的团队信息
     * @param isAgent                 是否为坐席
     * @return boolean 是否保存成功
     * @throws XbbException 封装的异常
     */
    @Override
    public boolean setAgent(String apiKey, CallCenterAccountEntity callCenterAccountEntity,
                            CallCenterTeamEntity callCenterTeamEntity, boolean isAgent) throws XbbException {
        if (callCenterAccountEntity == null || callCenterTeamEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
        }
        if (Objects.equals(callCenterAccountEntity.getModuleType(), CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode())) {
            // 客户未向度言平台注册
            if (StringUtil.isEmpty(callCenterAccountEntity.getAccountId())) {
                throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301037);
            } else if (StringUtil.isEmpty(callCenterTeamEntity.getTeamId())) {
                throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301038);
            }
            // 度言平台
            DuYanAccountVO duYanAccountVO;
            if (isAgent) {
                duYanAccountVO = duYanHttpService.setAgent(apiKey, callCenterAccountEntity.getAccountId(),
                        Long.parseLong(callCenterTeamEntity.getTeamId()), null);
                callCenterAccountEntity.setDepId(callCenterTeamEntity.getDepId());
                callCenterAccountEntity.setTeamId(callCenterTeamEntity.getTeamId());
            } else {
                duYanAccountVO = duYanHttpService.deleteAgent(apiKey, callCenterAccountEntity.getAccountId());
            }
            if (duYanAccountVO == null || duYanAccountVO.getAccountId() == null || duYanAccountVO.getIsAgent() == null) {
                throw new XbbException(DuYanErrorCodeEnum.API_ERROR_302003);
            }
            callCenterAccountEntity.setIsAgent(duYanAccountVO.getIsAgent() ? 1 : 0);
            return callCenterAccountModel.update(callCenterAccountEntity) > 0;

        } else if (Objects.equals(callCenterAccountEntity.getModuleType(), CallCenterTypeEnum.CALL_CENTER_XBB.getCode())) {
            if (isAgent) {
                callCenterAccountEntity.setDepId(callCenterTeamEntity.getDepId());
                callCenterAccountEntity.setTeamId(callCenterTeamEntity.getTeamId());
            }
            callCenterAccountEntity.setIsAgent(isAgent ? 1 : 0);
            return callCenterAccountModel.update(callCenterAccountEntity) > 0;
        }
        return false;
    }

    /**
     * 设置为话务中心的团队主管
     *
     * @param apiKey                  平台维护的apiKey
     * @param callCenterAccountEntity 话务平台员工信息
     * @param isSupervisor            是否为团队主管
     * @return boolean 是否保存成功
     * @throws XbbException 封装的异常
     */
    @Override
    public boolean setSupervisor(String apiKey, CallCenterAccountEntity callCenterAccountEntity, boolean isSupervisor) throws XbbException {
        if (callCenterAccountEntity == null) {
            // 客户未向度言平台注册
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
        }
        if (Objects.equals(callCenterAccountEntity.getModuleType(), CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode())) {
            if (StringUtil.isEmpty(callCenterAccountEntity.getAccountId())) {
                throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301037);
            }
            // 度言平台
            DuYanAccountVO duYanAccountVO;
            if (isSupervisor) {
                duYanAccountVO = duYanHttpService.setSupervisor(apiKey, callCenterAccountEntity.getAccountId());
            } else {
                duYanAccountVO = duYanHttpService.cancelSupervisor(apiKey, callCenterAccountEntity.getAccountId());
            }
            if (duYanAccountVO == null || duYanAccountVO.getAccountId() == null || duYanAccountVO.getIsSupervisor() == null) {
                throw new XbbException(DuYanErrorCodeEnum.API_ERROR_302003);
            }
            callCenterAccountEntity.setIsSupervisor(duYanAccountVO.getIsSupervisor() ? 1 : 0);
            return callCenterAccountModel.update(callCenterAccountEntity) > 0;
        } else if (Objects.equals(callCenterAccountEntity.getModuleType(), CallCenterTypeEnum.CALL_CENTER_XBB.getCode())) {
            callCenterAccountEntity.setIsSupervisor(isSupervisor ? 1 : 0);
            return callCenterAccountModel.update(callCenterAccountEntity) > 0;
        }
        return false;
    }

    /**
     * 设置为话务中心的超管
     *
     * @param apiKey                  平台维护的apiKey
     * @param callCenterAccountEntity 话务平台员工信息
     * @param isAdmin                 是否为超管
     * @return boolean 是否保存成功
     * @throws XbbException 封装的异常
     */
    @Override
    public boolean setAdmin(String apiKey, CallCenterAccountEntity callCenterAccountEntity, boolean isAdmin) throws XbbException {
        if (callCenterAccountEntity == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
        }
        if (Objects.equals(callCenterAccountEntity.getModuleType(), CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode())) {
            if (StringUtil.isEmpty(callCenterAccountEntity.getAccountId())) {
                throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301037);
            }
            // 度言平台
            DuYanAccountVO duYanAccountVO;
            if (isAdmin) {
                duYanAccountVO = duYanHttpService.setAdmin(apiKey, callCenterAccountEntity.getAccountId());
            } else {
                duYanAccountVO = duYanHttpService.cancelAdmin(apiKey, callCenterAccountEntity.getAccountId());
            }
            if (duYanAccountVO == null || duYanAccountVO.getAccountId() == null || duYanAccountVO.getIsAdmin() == null) {
                throw new XbbException(DuYanErrorCodeEnum.API_ERROR_302003);
            }
            callCenterAccountEntity.setIsAdmin(duYanAccountVO.getIsAdmin() ? 1 : 0);
            return callCenterAccountModel.update(callCenterAccountEntity) > 0;
        } else if (Objects.equals(callCenterAccountEntity.getModuleType(), CallCenterTypeEnum.CALL_CENTER_XBB.getCode())) {

            callCenterAccountEntity.setIsAdmin(isAdmin ? 1 : 0);
            return callCenterAccountModel.update(callCenterAccountEntity) > 0;
        }

        return false;
    }

    /**
     * 查询指定用户Id列表的用户
     *
     * @param callAccountUserIdInDTO 查询指定用户Id列表的用户入参
     * @return List<CallCenterAccountEntity>
     * @throws XbbException 封装的异常
     */
    @Override
    public List<CallCenterAccountEntity> getByUserIdIn(CallAccountUserIdInDTO callAccountUserIdInDTO) {
        if (callAccountUserIdInDTO.getUserIdIn().size() == 0) {
            return new ArrayList<>();
        }
        Map<String, Object> params = new HashMap<>(7);
        params.put("corpid", callAccountUserIdInDTO.getCorpid());
        if (callAccountUserIdInDTO.getDepId() != null) {
            params.put("depId", callAccountUserIdInDTO.getDepId());
        }
        params.put("moduleType", callAccountUserIdInDTO.getModuleType());
        params.put("userIdIn", callAccountUserIdInDTO.getUserIdIn());
        params.put("negDel", 1);
        params.put("start", 0);
        params.put("pageNum", callAccountUserIdInDTO.getUserIdIn().size());
        return callCenterAccountModel.findEntitys(params);
    }

    /**
     * 获取所有坐席的用户id
     *
     * @param corpid     公司id
     * @param moduleType 平台信息，参考AppStoreTypeEnum
     * @return List<String> 用户id队列
     * @author 章华隽
     * 创建时间：2018/1/2 下午9:40
     * 修改时间：
     * @version
     * @since 3.15.1
     */
    @Override
    public List<String> getAllAgentUserIdList(String corpid, Integer moduleType) {
        return getAgentUserIdList(corpid, moduleType, new HashMap<>(16));
    }

    /**
     * 获取所有坐席的用户id
     *
     * @param corpid     公司id
     * @param moduleType 平台信息，参考AppStoreTypeEnum
     * @param depId      部门id
     * @return List<String> 用户id队列
     * @author 章华隽
     * 创建时间：2018/1/2 下午9:40
     * 修改时间：
     * @version
     * @since 3.15.1
     */
    @Override
    public List<String> getSubAgentUserIdList(String corpid, Integer moduleType, Long depId) {
        if (depId == null) {
            return new ArrayList<>();
        }
        // 输入当前主管的部门id查询部门下的所有员工
        List<Long> depIdIn = new ArrayList<>();
        depIdIn.add(depId);
        List<String> userIdIn = userModel.getUserIdsRecursionDep(depIdIn, corpid, 1);
        if (userIdIn == null || userIdIn.size() == 0) {
            return new ArrayList<>();
        }
        Map<String, Object> params = new HashMap<>(16);
        params.put("userIdIn", userIdIn);
        return getAgentUserIdList(corpid, moduleType, params);
    }

    private List<String> getAgentUserIdList(String corpid, Integer moduleType, Map<String, Object> params) {
        params.put("corpid", corpid);
        params.put("negDel", DelEnum.DELETE.getDel());
        params.put("moduleType", moduleType);
        params.put("columns", "user_id");
        List<CallCenterAccountEntity> list = callCenterAccountModel.findEntitys(params);
        Set<String> userIdSet = new HashSet<>();
        for (CallCenterAccountEntity it : list) {
            userIdSet.add(it.getUserId());
        }
        return new ArrayList<>(userIdSet);
    }

    /**
     * 当设置坐席时，数据处理
     *
     * @param corpid        公司ID
     * @param moduleType    微应用标识，参考CallCenterTypeEnum
     * @param depId         部门ID
     * @param paidAgentNum  当月已经付费坐席数
     * @param teamEntity    根据销帮帮CRM的用户信息获取话务中心的团队账号
     * @param userInfoVO    话务中心平台注册账号
     * @param getByCorpIdVO 获取公司在该平台的公司信息
     * @param agentUserId   需要设置坐席的用户ID
     * @param agentNum      最大坐席上限(已经开通的坐席数量)
     * @throws XbbException
     */
    private void isAgent(String corpid, Integer moduleType, Long depId, Integer paidAgentNum,
                         CallCenterTeamEntity teamEntity, CallCenterAccountUserInfoVO userInfoVO,
                         CallCenterOrgGetByCorpIdVO getByCorpIdVO, String agentUserId, Integer agentNum) throws XbbException {
        // 只有是坐席的员工才有转团队的问题
        if (Objects.equals(userInfoVO.getIsAgent(), 1) && !Objects.equals(userInfoVO.getDepId(), null)) {
            // 设为坐席时需要先判断坐席团队是否与原有团队相同
            if (Objects.equals(depId, userInfoVO.getDepId())) {
                throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301039);
            } else {
                // 本次需要设置的员工的部门与员工本身的部门不符，提示用户切换部门
                String hint = paasRedisHelper.getValue(CallCenterConstant.REDIS_KEY_AGENT_CHANGE_DEP,
                        corpid + StringConstant.COLON + moduleType + StringConstant.COLON + agentUserId);
                if (StringUtil.isNotEmpty(hint)) {
                    // 已经提示过用户，进行切换部门保留角色的操作
                    if (!callCenterCommonService.changeAccountDep(corpid, userInfoVO, depId)) {
                        throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301040);
                    }
                } else {
                    paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_AGENT_CHANGE_DEP,
                            corpid + StringConstant.COLON + moduleType + StringConstant.COLON + agentUserId,
                            "changeDepHint", 60);
                    CallCenterTeamEntity originalTeamEntity = callCenterTeamService.getByXbbDepInfo(corpid, userInfoVO.getDepId(), moduleType);
                    if (originalTeamEntity == null) {
                        throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301034);
                    }
                    String errMsg = String.format(I18nMessageUtil.getMessage(CallCenterConstant.ERROR_MESSAGE_MEMBER_ONLY_BELONG_ONE_DEPARTMENT), userInfoVO.getName(),
                            originalTeamEntity.getName(), teamEntity.getName());
                    throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301012, errMsg);
                }
            }
        } else if (moduleType.equals(CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode())) {
            if (agentNum >= paidAgentNum) {
                // 当前用户还不是坐席，且坐席数超已付费坐席数
                // 尝试扣费再进行坐席设置
                if (!callCenterAgentStrategyService.consume(corpid, moduleType, Collections.singletonList(userInfoVO.getName()),
                        I18nMessageUtil.getMessage(I18nStringConstant.ADDITIONAL_SEATS))) {
                    throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301022);
                }
            }
        } else if (moduleType.equals(CallCenterTypeEnum.CALL_CENTER_XBB.getCode())) {
            Integer xbbAgentNum = getByCorpIdVO.getXbbAgentNum() == null ? Integer.valueOf(0) : getByCorpIdVO.getXbbAgentNum();
            if (agentNum >= xbbAgentNum) {
                throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301028);
            }
        }
    }

    /**
     * 线路分配
     *
     * @param userInfoVO 话务中心平台注册账号
     * @param apiKey     第三方话务中心方面维护的企业的apikey
     * @param teamEntity 根据销帮帮CRM的用户信息获取话务中心的团队账号
     * @param isAgent    是否设置成坐席
     * @param moduleType 微应用标识，参考CallCenterTypeEnum
     * @param agentNum   最大坐席上限(已经开通的坐席数量)
     * @param corpid     公司ID
     * @throws XbbException
     */
    private CallCenterAgentVO originTeamAgent(CallCenterAccountUserInfoVO userInfoVO, String apiKey, CallCenterTeamEntity teamEntity,
                                              Boolean isAgent, Integer moduleType, Integer agentNum, String corpid) throws XbbException {
        CallCenterAgentVO callCenterAgentVO = new CallCenterAgentVO();
        CallCenterAccountEntity accEntity = new CallCenterAccountEntity();
        BeanUtils.copyProperties(userInfoVO, accEntity);
        if (setAgent(apiKey, accEntity, teamEntity, isAgent)) {
            if (moduleType.equals(CallCenterTypeEnum.CALL_CENTER_DU_YAN.getCode())) {
                if (isAgent) {
                    agentNum++;
                    // 查找团队详情，查看是否分配了线路
                    CallCenterTeamEntity originTeam = callCenterTeamService.getOriginTeamDetail(apiKey,
                            teamEntity.getTeamId(), moduleType);
                    if (originTeam != null) {
                        if (!originTeam.getIsPhoneLine()) {
                            // 团队还未分配线路
                            callCenterAgentVO.setCode(CallCenterErrorCodeEnum.API_ERROR_301017.getCode());
                            callCenterAgentVO.setMsg(CallCenterErrorCodeEnum.API_ERROR_301017.getMsg());
                        }
                        callCenterTeamService.syncOriginTeamDetail(teamEntity, originTeam);
                    }
                } else {
                    agentNum--;
                    agentNum = agentNum < 0 ? 0 : agentNum;
                }
            }
            paasRedisHelper.setValue(CallCenterConstant.REDIS_KEY_AGENT_NUM, corpid + StringConstant.COLON + moduleType,
                    agentNum.toString(), RedisConstant.COMMON_DURATION);
        } else {
            throw new XbbException(CallCenterErrorCodeEnum.API_ERROR_301041);
        }
        return callCenterAgentVO;
    }
}
